import { NInput } from "naive-ui";
import type { BaseComponentType, OmitHTMLAttributes } from "../types";
import type { InputProps, InputInst } from "naive-ui";
import { getSlotsDom } from "../utils";

export type InputFactoryConstructorType = {
  props?: InputProps;
  attrs?: OmitHTMLAttributes<"onChange" | "onInput">;
  clearIconSlot?: BaseComponentType;
  suffixSlot?: BaseComponentType;
  prefixSlot?: BaseComponentType;
  countSlot?: (v?: { value: string }) => BaseComponentType;
  passwordInvisibleIconSlot?: BaseComponentType;
  passwordVisibleIconSlot?: BaseComponentType;
  separatorSlot?: BaseComponentType;
};

export class InputFactory {
  private attrs: OmitHTMLAttributes<"onChange" | "onInput"> = {};
  private props: InputProps = {};

  private clearIconSlot: BaseComponentType = null;
  private suffixSlot: BaseComponentType = null;
  private prefixSlot: BaseComponentType = null;
  private countSlot: (v?: { value: string }) => BaseComponentType = () => null;
  private passwordInvisibleIconSlot: BaseComponentType = null;
  private passwordVisibleIconSlot: BaseComponentType = null;
  private separatorSlot: BaseComponentType = null;

  private domRef: InputInst | null = null;

  constructor(data?: InputFactoryConstructorType) {
    if (data?.props) this.setProps(data.props);
    if (data?.attrs) this.setAttrs(data.attrs);
    if (data?.clearIconSlot) this.setClearIcon(data.clearIconSlot);
    if (data?.suffixSlot) this.setSuffix(data.suffixSlot);
    if (data?.prefixSlot) this.setPrefix(data.prefixSlot);
    if (data?.countSlot) this.setCount(data.countSlot);
    if (data?.passwordInvisibleIconSlot)
      this.setPasswordInvisibleIcon(data.passwordInvisibleIconSlot);
    if (data?.passwordVisibleIconSlot)
      this.setPasswordVisibleIcon(data.passwordVisibleIconSlot);
    if (data?.separatorSlot) this.setSeparator(data.separatorSlot);
  }

  setAttrs(attrs: OmitHTMLAttributes<"onChange" | "onInput">) {
    this.attrs = attrs;
    return this;
  }

  setProps(props: InputProps) {
    this.props = props;
    return this;
  }

  setClearIcon(component: BaseComponentType) {
    this.clearIconSlot = component;
    return this;
  }

  setSuffix(component: BaseComponentType) {
    this.suffixSlot = component;
    return this;
  }

  setPrefix(component: BaseComponentType) {
    this.prefixSlot = component;
    return this;
  }

  setCount(component: (v?: { value: string }) => BaseComponentType) {
    this.countSlot = component;
    return this;
  }

  setPasswordInvisibleIcon(component: BaseComponentType) {
    this.passwordInvisibleIconSlot = component;
    return this;
  }

  setPasswordVisibleIcon(component: BaseComponentType) {
    this.passwordVisibleIconSlot = component;
    return this;
  }

  setSeparator(component: BaseComponentType) {
    this.separatorSlot = component;
    return this;
  }
  blur() {
    this.domRef?.blur();
  }
  clear() {
    this.domRef?.clear();
  }
  focus() {
    this.domRef?.focus();
  }
  select() {
    this.domRef?.select();
  }
  scrollTo(v: { left?: number; top?: number; behavior?: "auto" | "smooth" }) {
    this.domRef?.scrollTo(v);
  }

  create() {
    return (
      <NInput
        ref={(el: HTMLElement) => {
          this.domRef = el as unknown as InputInst;
        }}
        {...this.props}
        {...this.attrs}
      >
        {{
          //   default: () => getSlotsDom(this.defaultSlot),
          "clear-icon": () => getSlotsDom(this.clearIconSlot),
          suffix: () => getSlotsDom(this.suffixSlot),
          prefix: () => getSlotsDom(this.prefixSlot),
          count: (v: { value: string }) => getSlotsDom(this.countSlot(v)),
          "password-invisible-icon": () =>
            getSlotsDom(this.passwordInvisibleIconSlot),
          "password-visible-icon": () =>
            getSlotsDom(this.passwordVisibleIconSlot),
          separator: () => getSlotsDom(this.separatorSlot),
        }}
      </NInput>
    );
  }
}
